package cn.initcap.algorithm.swing.getpiwithmontecarlo;

import cn.initcap.algorithm.swing.AlgoVisHelper;
import cn.initcap.algorithm.swing.BaseAlgoFrame;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.Random;

/**
 * @author initcap
 * @date 2018/8/3 AM10:27
 */
public class AlgoVisualizer {

    private static int DELAY = 40;
    private MonteCarloPiData data;
    private BaseAlgoFrame frame;
    private int n;

    public AlgoVisualizer(int sceneWidth, int sceneHeight, int n) {

        if (sceneWidth != sceneHeight) {
            throw new IllegalArgumentException("This demo must be run in a square window!");
        }
        this.n = n;
        Circle circle = new Circle(sceneWidth / 2, sceneHeight / 2, sceneWidth / 2);
        data = new MonteCarloPiData(circle);

        // 初始化视图
        EventQueue.invokeLater(() -> {
            frame = new BaseAlgoFrame("Monte Carlo", sceneWidth, sceneHeight) {
                @Override
                public void draw(Graphics graphics) {
                    Graphics2D g2d = (Graphics2D) graphics;
                    AlgoVisHelper.setStrokeWidth(g2d, 3);
                    AlgoVisHelper.setColor(g2d, AlgoVisHelper.BLUE);
                    Circle circle = data.getCircle();
                    AlgoVisHelper.strokeCircle(g2d, circle.getX(), circle.getY(), circle.getR());

                    for (int i = 0; i < data.getPointsNumber(); i++) {
                        Point p = data.getPoint(i);
                        if (circle.contain(p)) {
                            AlgoVisHelper.setColor(g2d, AlgoVisHelper.RED);
                        } else {
                            AlgoVisHelper.setColor(g2d, AlgoVisHelper.GREEN);
                        }
                        AlgoVisHelper.fillCircle(g2d, p.x, p.y, 3);
                    }
                }
            };

            new Thread(() -> {
                run();
            }).start();
        });
    }

    public static void main(String[] args) {

        int sceneWidth = 800;
        int sceneHeight = 800;
        int n = 20000;

        new AlgoVisualizer(sceneWidth, sceneHeight, n);
    }

    public void run() {

        for (int i = 0; i < n; i++) {

            if (i % 100 == 0) {
                frame.render(data);
                AlgoVisHelper.pause(DELAY);
                System.out.println(data.estimatePi());
            }

            int x = new Random().nextInt(frame.getCanvasWidth());
            int y = new Random().nextInt(frame.getCanvasWidth());
            data.addPoint(new Point(x, y));
        }

    }
}
